#include "math_3d.h"
#define GLEW_STATIC 1
#include <GL/glew.h>
#include <glut.h>
#include "Timer.h"
#include "Clock.h"
#include <assert.h>
#include "glwindow.h"


#define FPS 60
#define TIMER_FREQ 1000/FPS
static Timer timer;
static int frameCount = 0;
static Timing::Clock clck;

static void (*RenderSceneCb)(void) = NULL;
static void (*UpdateSceneCb)(float time) = NULL;
static void (*ReshapeWindowCb)(int width, int height);
static void (*KeyBoardFunCb)(unsigned char key,int x,int y);
static void (*InitSceneCb)(void);

static void RenderScene(void)
{
	if(RenderSceneCb != NULL)
		RenderSceneCb();
}

static void IdleFunction(void)
{
	float seconds = (float) timer.getElapsedTime();
	if(seconds > 1)
	{
		printf("FPS = %d\n",(int)(frameCount/seconds));
		frameCount = 0;
		timer.start();
	}
	//printf("%lf\n",timer.getElapsedTime());
}

static void UpdateScene(int param)
{

	clck.newFrame();
	if(UpdateSceneCb != NULL)
		UpdateSceneCb(clck.timeElapsedLastFrame());
	glutTimerFunc(TIMER_FREQ,UpdateScene,1);
	glutPostRedisplay();
	frameCount++;
}

static void ReshapeWindow(int width, int height)
{
	if(ReshapeWindowCb != NULL)
		ReshapeWindowCb(width,height);

}
void KeyBoardFunc(unsigned char key,int x,int y)
{
	if(KeyBoardFunCb != NULL)
		KeyBoardFunCb(key,x,y);


		
}

void GLWindowCreate(int width,int height)
{
	// Assumes the glutInit is already called
    glutInitDisplayMode(GLUT_DOUBLE|GLUT_RGBA);
    glutInitWindowSize(width, height);
    glutInitWindowPosition(100, 100);
    glutCreateWindow("Application");

	glutDisplayFunc(RenderScene);
	glutIdleFunc(IdleFunction);
	glutTimerFunc(TIMER_FREQ,UpdateScene,1);
	glutReshapeFunc(ReshapeWindow);
	glutKeyboardFunc(KeyBoardFunc);


	GLenum res = glewInit();
	assert(GLEW_OK == res);
	assert(clck.initialize());
	
	    
}

void GLWindowStart(void)
{

	InitSceneCb();
	timer.start();
	glutMainLoop();
	
	// Free all resources
	clck.shutdown();
}

void SetInitSceneCallBack(void (*InitSceneCbFunc)(void))
{
	InitSceneCb = InitSceneCbFunc;
}
void SetUpdateSceneCallBack(void (*UpdateSceneCbFunc)(float delta_time))
{
	UpdateSceneCb = UpdateSceneCbFunc;
}


void SetUpKeyboardCallBack(void  (*KeyBoardFunCbFunc)(unsigned char key,int x,int y))
{
	KeyBoardFunCb = KeyBoardFunCbFunc;
}

void SetRenderSceneCallBack(void (*RenderSceneCbFunc)(void))
{
	RenderSceneCb = RenderSceneCbFunc;
}

void SetReshapeWindowCallBack(void (*ReshapeWindowCbFunc)(int width,int height))
{
	ReshapeWindowCb = ReshapeWindowCbFunc;
}
